package io.youngledo.usb.task;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.function.Consumer;

/**
 * 支持进度跟踪的输入流包装器
 * 在读取数据时自动更新进度跟踪器
 */
public class ProgressInputStream extends FilterInputStream {

    private final ProgressUpdater progressUpdater;

    /**
     * 使用ProgressTracker构造
     */
    public ProgressInputStream(InputStream inputStream, ProgressTracker progressTracker) {
        super(inputStream);
        this.progressUpdater = new ProgressUpdater(progressTracker, () -> {
            try {
                close();
            } catch (IOException e) {
                // 忽略关闭时的异常
            }
        });
    }

    /**
     * 使用回调函数构造
     */
    public ProgressInputStream(InputStream inputStream, Consumer<Long> progressCallback) {
        super(inputStream);
        this.progressUpdater = new ProgressUpdater(progressCallback, () -> {
            try {
                close();
            } catch (IOException e) {
                // 忽略关闭时的异常
            }
        });
    }

    @Override
    public int read() throws IOException {
        int b = super.read();
        if (b != -1) {
            progressUpdater.updateProgress(1);
        }
        return b;
    }

    @Override
    public int read(byte[] buffer) throws IOException {
        return read(buffer, 0, buffer.length);
    }

    @Override
    public int read(byte[] buffer, int offset, int length) throws IOException {
        int bytesRead = super.read(buffer, offset, length);
        if (bytesRead > 0) {
            progressUpdater.updateProgress(bytesRead);
        }
        return bytesRead;
    }

    @Override
    public long skip(long n) throws IOException {
        long skipped = super.skip(n);
        if (skipped > 0) {
            progressUpdater.updateProgress(skipped);
        }
        return skipped;
    }

    @Override
    public void close() throws IOException {
        try {
            progressUpdater.finalizeProgress();
        } finally {
            super.close();
        }
    }

    public long getTotalBytesRead() {
        return progressUpdater.getTotalBytesProcessed();
    }
}